// this is an utilitary class allowing scene elements to animate
// all animations will be stored into an array allowing the stopAllAnimations function to work
// animateMove - moves the animation object to the new position in a straight line
// V 2.0 - uses requestAnimFrame native functions, or falls back to setTimeout
window.requestAnimFrame = (function(){
	return  window.requestAnimationFrame   ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			window.oRequestAnimationFrame      ||
			window.msRequestAnimationFrame     ||
			function(/* function */ callback, /* DOMElement */ element){
				console.log("using timeout fallback");
				return window.setTimeout(callback, 1000 / 60);
			};
})();

// initiates animation
canvasAnimate = function (animationStep) {
	var self = this;
	return window.requestAnimFrame( animationStep );	
}
// animations list
var canvasAnimations = new Array();

// animation class
function Animation(obj, options){
	// shape to be animated
	this.obj = obj;
	// default speed - the default animation speed
	this.speed = (options && options.speed)?options.speed:30;
	// animation status - 0 not animating, 1 animating
	this.status = 0;
	// animation interval object, will be cleared when animation is finished or stopped
	this.interval = null;

	this.precision = 1;
	this.currentTry = 1;

	// adds this animation to the list, allowing for stopAllAnimations function
	canvasAnimations.push(this);
	
	// check options
	if(options){
		// check if time is to be used instead of speed
		// if time is selected, the animation will take that amount of time to complete
		if(options.mode=="time") this.mode=2;
	}
	
	// moves a shape in a straight line to a new position
	this.animateMove = function(x, y, speed, progress, finish){
		// do not animate if already animating
		if(this.status==1){
			if(typeof(finish)=="function") finish();
			return;
		}
		// set attributes anr parameters
		var self = this;
		this.status = 1;
		var origX = this.obj.x;
		var origY = this.obj.y;
	
		speed = speed |this.speed;


		var tx = x-origX,
            ty = y-origY,
            distance = Math.sqrt(tx*tx+ty*ty),
            rad = Math.atan2(ty,tx),
            angle = rad/Math.PI * 180;
    
        
		var speedX = (tx/distance)*speed;
        var speedY = (ty/distance)*speed;
		
		var initialStep = new Date().getTime();
		var lastStep = initialStep;
	
		var animationStep = function(){
			if(self.status==2) return;
			if(self.currentTry<self.precision){
				self.currentTry++;
				self.interval = canvasAnimate(animationStep);
				return;
			}
			self.currentTry = 1;
			var currentStep = new Date().getTime();
			var dist = (currentStep-initialStep)/1000 * speed;	
			if(dist>=distance)dist = distance;
			var dx=(currentStep-initialStep)/1000 * speedX;
			var dy=(currentStep-initialStep)/1000 * speedY;
			self.obj.move(origX+dx,origY+dy);
			lastStep = currentStep;	
			if(dist>=distance){	
				// finished animation callback
				self.status = 0;
				if(typeof(finish)=="function") finish();				
				return;
			}
			else{
				// call progress					
				if(typeof(progress)=="function") progress(Math.floor(dist/distance * 100));
			}
			self.interval = canvasAnimate(animationStep);	
		}
		self.interval = canvasAnimate(animationStep);					
	};
	
	// stop current animation
	this.stop = function(){				
		this.status=2;
	};
}

// stop all animations
function stopAllCanvasAnimations(){
	for(var k in canvasAnimations){
		var anim = canvasAnimations[k];
		anim.stop();
	}
}

